#define _LCD_MODULE_
#include "osObjects.h"
#include "gd32f20x.h"
#include "gd32f20x_gpio.h"
#include "gd32f20x_rcc.h"
#include "gd32f20x_tldi.h"
#include "gd32f20x_exmc.h"
#include "lcdctr.h"
#include "pincfg.h"
#include "picture.h"
#include "gd32f20cl_eval_lcd.h"
#include "exmc_sdram.h"

TLDI_Layer_InitPara TLDI_Layer_InitStruct;
extern uint32_t KeyDownCnt;

#define SDRAM_BANK1_ADDR                 (0xC0000000UL)
#define ADDR_OFFSET_LAYER2BUFF1          (0x1000)
#define ADDR_OFFSET_LAYER2BUFF2          (ADDR_OFFSET_LAYER2BUFF1+480*272*2)
#define ADDR_OFFSET_LAYER1BUFF1          (ADDR_OFFSET_LAYER2BUFF2+480*272*2)
#define ADDR_OFFSET_LAYER1BUFF2          (ADDR_OFFSET_LAYER1BUFF1+480*272*2)
#define ADDR_OFFSET_LAYER1BUFF3          (ADDR_OFFSET_LAYER1BUFF2+480*272*2)

#define ADDR_LAYER2BUFF1                 (SDRAM_BANK1_ADDR + ADDR_OFFSET_LAYER2BUFF1)
#define ADDR_LAYER2BUFF2                 (SDRAM_BANK1_ADDR + ADDR_OFFSET_LAYER2BUFF2)
#define ADDR_LAYER1BUFF1                 (SDRAM_BANK1_ADDR + ADDR_OFFSET_LAYER1BUFF1)
#define ADDR_LAYER1BUFF2                 (SDRAM_BANK1_ADDR + ADDR_OFFSET_LAYER1BUFF2)
#define ADDR_LAYER1BUFF3                 (SDRAM_BANK1_ADDR + ADDR_OFFSET_LAYER1BUFF3)

#define  LayerBuff1                      ((uint16_t *)(SDRAM_BANK1_ADDR + ADDR_OFFSET_LAYER2BUFF1))
#define  LayerBuff2                      ((uint16_t *)(SDRAM_BANK1_ADDR + ADDR_OFFSET_LAYER2BUFF2))
#define  LayerGBuff1                     ((uint16_t *)(SDRAM_BANK1_ADDR + ADDR_OFFSET_LAYER1BUFF1))
#define  LayerGBuff2                     ((uint16_t *)(SDRAM_BANK1_ADDR + ADDR_OFFSET_LAYER1BUFF2))
#define  LayerGBuff3                     ((uint16_t *)(SDRAM_BANK1_ADDR + ADDR_OFFSET_LAYER1BUFF3))

uint32_t BackGroundSite;

void LcdIntCfg(void);

/*****************************************************************************//*!
*
* @brief   lcd task.
*     
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void LcdCtrTask(void * pPar)
{
    OS_ERR      os_err;
    
    uint32_t    Cnt;
    uint32_t    Line;
    uint32_t    Row;
    uint32_t    Step;
    
    OSTimeDly(100, OS_OPT_TIME_DLY, &os_err);
    BackGroundSite = 0;
    
    Cnt = 480*272;
    while(Cnt--)
    {
        LayerGBuff1[Cnt] = ((uint16_t*)gImage_background)[Cnt];
       
    } 
    
    LcdInit();
    LcdIntCfg();
    //TLDI_Layer_Enable(TLDI_Layer2, ENABLE);
    
    TLDI_Layer1->FBSAR = ADDR_LAYER1BUFF1; 
    TLDI_Layer_Enable(TLDI_Layer1, ENABLE);
    TLDI_ReloadConfig(TLDI_RELOADLAYERTYPE_FBR);
    
    Cnt = 480*272;
    while(Cnt--)
    {
        LayerBuff1[Cnt] = 0xFFFF;
        LayerBuff2[Cnt] = 0xFFFF;
        LayerGBuff1[Cnt] = LayerGBuff3[Cnt] = ((uint16_t*)gImage_background)[Cnt];
        LayerGBuff2[Cnt] = ((uint16_t*)gImage_background)[Cnt+0x20000];
    } 
    
    Line = 272;
    Row  = 17;
    Step = 0;
    for(;;)
    {
        switch(Step)
        {
            case 0:
                Line--;
                LayerBuff1[Row+ Line*480] = LCD_COLOR_BLUE2; 
                LayerBuff1[Row+ Line*480+1] = LCD_COLOR_BLUE2; 
                LayerBuff1[Row+ Line*480+2] = LCD_COLOR_BLUE2; 
                LayerBuff1[Row+ Line*480+3] = LCD_COLOR_BLUE2;
                LayerBuff1[Row+ Line*480+4] = LCD_COLOR_BLUE2;
                if(0 == Line)
                {
                    Step++;
                }
                break;
            case 1:
                Row++;
                LayerBuff1[Row+ Line*480] = LCD_COLOR_BLUE2; 
                LayerBuff1[Row+ (Line+1)*480] = LCD_COLOR_BLUE2; 
                LayerBuff1[Row+ (Line+2)*480] = LCD_COLOR_BLUE2; 
                LayerBuff1[Row+ (Line+3)*480] = LCD_COLOR_BLUE2;
                LayerBuff1[Row+ (Line+4)*480] = LCD_COLOR_BLUE2;
                if(Row >= (480-19) )
                {
                    Step++;
                }
                break;
            case 2:
                Line++;
                LayerBuff1[Row+ Line*480] = LCD_COLOR_BLUE2; 
                LayerBuff1[Row+ (Line)*480 - 1] = LCD_COLOR_BLUE2; 
                LayerBuff1[Row+ (Line)*480 - 2] = LCD_COLOR_BLUE2; 
                LayerBuff1[Row+ (Line)*480 - 3] = LCD_COLOR_BLUE2;   
                LayerBuff1[Row+ (Line)*480 - 4] = LCD_COLOR_BLUE2;  
                if(Line >= (271) )
                {
                    Step++;
                }
                break;
            case 3:
                Row--;
                LayerBuff1[Row+ Line*480] = LCD_COLOR_BLUE2; 
                LayerBuff1[Row+ (Line - 1)*480] = LCD_COLOR_BLUE2; 
                LayerBuff1[Row+ (Line - 2)*480] = LCD_COLOR_BLUE2; 
                LayerBuff1[Row+ (Line - 3)*480] = LCD_COLOR_BLUE2; 
                LayerBuff1[Row+ (Line - 4)*480] = LCD_COLOR_BLUE2; 
                if(Row <= 19 )
                {
                    Step++;
                    Line = 272;
                    Row  = 17;
                }
                break;
             case 4:
                Line--;
                LayerBuff1[Row+ Line*480] = 0xFFFF; 
                LayerBuff1[Row+ Line*480+1] = 0xFFFF; 
                LayerBuff1[Row+ Line*480+2] = 0xFFFF; 
                LayerBuff1[Row+ Line*480+3] = 0xFFFF;
                LayerBuff1[Row+ Line*480+4] = 0xFFFF;
                if(0 == Line)
                {
                    Step++;
                }
                break;
            case 5:
                Row++;
                LayerBuff1[Row+ Line*480] = 0xFFFF; 
                LayerBuff1[Row+ (Line+1)*480] = 0xFFFF; 
                LayerBuff1[Row+ (Line+2)*480] = 0xFFFF; 
                LayerBuff1[Row+ (Line+3)*480] = 0xFFFF;
                LayerBuff1[Row+ (Line+4)*480] = 0xFFFF;
                if(Row >= (480-19) )
                {
                    Step++;
                }
                break;
            case 6:
                Line++;
                LayerBuff1[Row+ Line*480] = 0xFFFF; 
                LayerBuff1[Row+ (Line)*480 - 1] = 0xFFFF; 
                LayerBuff1[Row+ (Line)*480 - 2] = 0xFFFF; 
                LayerBuff1[Row+ (Line)*480 - 3] = 0xFFFF;   
                LayerBuff1[Row+ (Line)*480 - 4] = 0xFFFF;  
                if(Line >= (271) )
                {
                    Step++;
                }
                break;
            case 7:
                Row--;
                LayerBuff1[Row+ Line*480] = 0xFFFF; 
                LayerBuff1[Row+ (Line - 1)*480] = 0xFFFF; 
                LayerBuff1[Row+ (Line - 2)*480] = 0xFFFF; 
                LayerBuff1[Row+ (Line - 3)*480] = 0xFFFF; 
                LayerBuff1[Row+ (Line - 4)*480] = 0xFFFF; 
                if(Row <= 19 )
                {
                    Line = 272;
                    Row  = 17;
                    Step = 0;
                }
                break;
            default:
                break;
        }
        
        OSTimeDly(8, OS_OPT_TIME_DLY, &os_err);
        LCD_layer2Display();
    }
}


/*****************************************************************************//*!
*
* @brief   led control init.
*     
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void LcdInit(void)
{
    LCD_Init();
    LCD_LayerInit();
    TLDI_ReloadConfig(TLDI_RELOADLAYERTYPE_RQR);
    TLDI_Enable(ENABLE);
}

void LcdIntCfg(void)
{
    TLDI->LRFR = 270;
    //TLDI->IMR |= TLDI_IMR_LRIM;
    //TLDI->CFR |= TLDI_CFR_CLR;
    
    NVIC_SetPriority(TLDI_IRQn, 0xC0);
	NVIC_ClearPendingIRQ(TLDI_IRQn);
	NVIC_EnableIRQ(TLDI_IRQn);	
}

/*****************************************************************************//*!
*
* @brief   lcd layer2 control.
*     
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void LCD_layer2Display(void)
{
    //OS_ERR      os_err;
    
    TLDI_Layer1->FBSAR = ADDR_LAYER1BUFF1 + BackGroundSite*480*2; 
    TLDI_ReloadConfig(TLDI_RELOADLAYERTYPE_FBR);
    
    if(BackGroundSite < 272*2)
    {
        if(KeyDownCnt&0x01)
        {
            if((BackGroundSite%(272)) != 0)
                BackGroundSite ++;
        }
        else
        {
            BackGroundSite ++;
        }
    }
    else
    {
        BackGroundSite=0;
    }
    
    /*
    TLDI_Layer2->FBSAR = (uint32_t)&gImage_0;  
    TLDI_ReloadConfig(TLDI_RELOADLAYERTYPE_FBR);
    
    OSTimeDly(200, OS_OPT_TIME_DLY, &os_err);
    
    TLDI_Layer2->FBSAR = (uint32_t)&gImage_1;  
    TLDI_ReloadConfig(TLDI_RELOADLAYERTYPE_FBR);
    
    OSTimeDly(160, OS_OPT_TIME_DLY, &os_err);
    
    TLDI_Layer2->FBSAR = (uint32_t)&gImage_2;  
    TLDI_ReloadConfig(TLDI_RELOADLAYERTYPE_FBR);
    
    OSTimeDly(120, OS_OPT_TIME_DLY, &os_err);
    
    TLDI_Layer2->FBSAR = (uint32_t)&gImage_3;  
    TLDI_ReloadConfig(TLDI_RELOADLAYERTYPE_FBR);
    
    OSTimeDly(100, OS_OPT_TIME_DLY, &os_err);
    
    TLDI_Layer2->FBSAR = (uint32_t)&gImage_4;  
    TLDI_ReloadConfig(TLDI_RELOADLAYERTYPE_FBR);
    
    OSTimeDly(100, OS_OPT_TIME_DLY, &os_err);
    
    TLDI_Layer2->FBSAR = (uint32_t)&gImage_3;  
    TLDI_ReloadConfig(TLDI_RELOADLAYERTYPE_FBR);
    
    OSTimeDly(140, OS_OPT_TIME_DLY, &os_err);
    
    TLDI_Layer2->FBSAR = (uint32_t)&gImage_2;  
    TLDI_ReloadConfig(TLDI_RELOADLAYERTYPE_FBR);
    
    OSTimeDly(180, OS_OPT_TIME_DLY, &os_err);
    
    TLDI_Layer2->FBSAR = (uint32_t)&gImage_1;  
    TLDI_ReloadConfig(TLDI_RELOADLAYERTYPE_FBR);
    
    OSTimeDly(200, OS_OPT_TIME_DLY, &os_err);
    */
}


void TLDI_IRQHandler()
{
    TLDI->CFR |= TLDI_CFR_CLR;
    TLDI_ReloadConfig(TLDI_RELOADLAYERTYPE_RQR);
}

